﻿using System;
using System.Data;
using System.Transactions;
using Infrastructure.Messages;
using Infrastructure.Persistence;

namespace SocialFront.Core.Commands
{
    public abstract class Command
    {
        protected readonly IRepository Repository;
        protected virtual void Validate() { }
        protected abstract void ExecuteChange();

        protected Command(IRepository repository = null)
        {
            Repository = repository ?? Facade.Repository;
        }

        protected void ValidateAndExecuteChange()
        {
            Validate();
            ExecuteChange();
        }

        public ResponseBase Execute()
        {
            var response = new ResponseBase();
            var saved = false;

            using (var transaction = new TransactionScope())
            {
                try
                {
                    ValidateAndExecuteChange();
                    saved = true;
                    response.Success = true;
                }
                catch (OptimisticConcurrencyException)
                {
                    Repository.SaveChanges();
                    saved = true;
                }
                catch (Exception e)
                {
                    response.Success = false;
                    response.Message = e.Message;
                    // Log to Elmah. 
                }
                finally
                {
                    if (saved)
                        transaction.Complete();
                }
            }
            return response;
        }
    }
}